// Some of the API Functions below are derived from GPL code originally by Flock Inc:
// Released under the same GLP license.
//
// For the original source, see: http://cvs-mirror.flock.com/index.cgi/mozilla/browser/components/flock/blog/content/blogapi.js?rev=1.19&content-type=text/vnd.viewcvs-markup
// and http://cvs-mirror.flock.com/index.cgi/mozilla/browser/components/flock/blog/content/
//
// Usage: myblog.init('blogger', '0123456789ABCDEF', 'http://plant.blogger.com/api/RPC2' ,'3724458', null, 'BillyBob',  'bbBaby'  )


var gPFFDebugTemp = [];

var perFormancingBlogAPI= function () {
    this.addCategories = false;
    this.extendedEntries = false;
	
	this.supportsPages = false;
	this.supportsCustomFields = false;
	this.supportsTags = false;
	this.supportsDrafts = true;
	
	this.standard = true;
}

perFormancingBlogAPI.prototype = {
    init: function (aName, aAppKey, aAPILink, aBlogID, aPreferred, aUsername, aPassword, aNeedsAuth) {
        this.name = aName;
        this.appKey = aAppKey;
        this.editLink = "";
        this.apiLink = aAPILink;
        this.appKey = "";
        this.blogID = aBlogID;
        this.username = aUsername;
        this.password = aPassword;
        this.needsAuth = aNeedsAuth;
    },
    setAuth: function (aUsername, aPassword, aURL){},
    doSetup: function (){},
    doAuth: function (aUsername, aPassword) {},
    newPost: function (aTitle, aDescription, aArrayOfCats, aDateCreated, aPublish) {},
    editPost: function (aPostid, aTitle, aDescription, aArrayOfCats, aDateCreated, aPublish) {},
    deletePost: function (aPostid, aEditURI) {},
	deletePage: function (pageId) {},
    getUsersBlogs: function () {},
    getRecentPosts: function (aNumber) {},
    setPostCategories: function (aPostid, aCategories) {},
    getCategoryList: function () {},
    publishPost: function (aPostid) {},
    fileUpload: function (aFileName, aMimeType, aDataString) {},
    aggregateCategories : function (catArray) {}
}

//This Function is derived from GPL code originally by Flock Inc:
//myblog = new perFormancingBloggerAPI()
var perFormancingBloggerAPI = function () {
    this.newPost = function (aTitle, aDescription, aArrayOfCats, aDateCreated, aPublish) {
		// Doesn't support dateCreated
        var argArray = [this.apiLink, this.appKey, this.blogID, this.username, this.password, aDescription, aPublish];
        return performancingAPICalls.blogger_newPost(argArray);
    };
    this.editPost = function (aPostid, aTitle, aDescription, aArrayOfCats, aDateCreated, aPublish) { 
		// Doesn't support dateCreated
        var argArray = [this.apiLink, this.appKey, aPostid, this.username, this.password, aDescription, aPublish];
        return performancingAPICalls.blogger_editPost(argArray);
    };
    this.deletePost = function (aPostid) {
        var argArray = [this.apiLink, this.appKey, aPostid, this.username, this.password, true];
        return performancingAPICalls.blogger_deletePost(argArray);
    };
	this.deletePage = function (pageId) {
		return false;
	};
    this.getUsersBlogs = function () {
        var argArray = [this.apiLink, this.appKey, this.username, this.password];
        return performancingAPICalls.blogger_getUsersBlogs(argArray);
    };
    this.getRecentPosts = function () {
        var argArray = [this.apiLink, this.appKey, this.blogID, this.username, this.password, 50];
        return performancingAPICalls.blogger_getRecentPosts(argArray);
    };
    this.getCategoryList = function (argArray) { //Not available
		return false;
    };
    this.setPostCategories = function (aPostid, aCategories) { //Not Available
        return false;
    };
    this.publishPost = function (aPostid) {
        return false;
    };
}
perFormancingBloggerAPI.prototype = new perFormancingBlogAPI();

var scribefireAdsAPI = {
	apiLink : "http://www.scribefire.com/scribefire_api/",
	authToken : null,
	
	signup : function (aUsername, aPassword) {
		var argArray = [this.apiLink, { login: aUsername, password: aPassword }];
		return bfXMLRPC.makeXML("account.add", argArray);
	},
	
	signin : function (aUsername, aPassword) {
		return bfXMLRPC.makeXML("account.login", [ this.apiLink, aUsername, aPassword ]);
	},
	
	signout : function () {
		return bfXMLRPC.makeXML("account.logout", [ this.apiLink, this.authToken ]);
	},
	
	addWebsite : function (url, name) {
		return bfXMLRPC.makeXML("website.add", [ this.apiLink, this.authToken, { "url" : url, "title" : name, "description" : "" } ]);
	},
	
	addInText : function (websiteId, name, url) {
		return bfXMLRPC.makeXML("campaign.addintext", [ this.apiLink, this.authToken, { "name" : name, "website_id" : websiteId, "url" : url } ]);
	},
	
	getWebsites : function () {
		return bfXMLRPC.makeXML("website.list", [ this.apiLink, this.authToken ]);
	},
	
	saveAd : function (websiteId, location, name, width, height) {
		return bfXMLRPC.makeXML("campaign.add", [ this.apiLink, this.authToken, { "ad_placement" : location, "name" : name, "ad_height" : height, "ad_width" : width, "website_id" : websiteId }]);
	},
	
	getEarnings : function (start, end) {
		return bfXMLRPC.makeXML("earnings.get", [ this.apiLink, this.authToken, start, end ]);
	},
	
	getAdCode : function (url) {
		return bfXMLRPC.makeXML("ad.placementJS", [ this.apiLink, this.authToken ]);
	},
	
	deleteWebsite : function (url) {
		return bfXMLRPC.makeXML("website.delete", [ this.apiLink, this.authToken, { "url" : url }]);
	},
	
	deleteCampaign : function (campaignId, url) {
		return bfXMLRPC.makeXML("campaign.delete", [ this.apiLink, this.authToken, {"id": campaignId, "url" : url } ]);
	},
	
	deletePlacement : function (campaignId, placement) {
		return bfXMLRPC.makeXML("adPlacement.delete", [ this.apiLink, this.authToken, { "campaign_id" : campaignId, "placement" : placement }]);
	},
	
	getCampaigns : function () {
		return bfXMLRPC.makeXML("campaign.list.all", [ this.apiLink, this.authToken ]);
	},
	
	deleteWebsiteCampaigns : function (url) {
		return bfXMLRPC.makeXML("campaign.delete", [ this.apiLink, this.authToken, {"url" : url}]);
	}
};

//This Function is derived from GPL code originally by Flock Inc:
var performancingMetaweblogAPI = function () {
    this.newPost = function (aTitle, aDescription, aArrayOfCats, aDateCreated, aPublish, NOTUSED1, slug) {
		var ourNewDate = "";

        if(aDateCreated != ""){
           ourNewDate = new Date(aDateCreated)
        }
		
        var content_t =
        {
            title: aTitle,
            description: aDescription,
            categories: aArrayOfCats,
			dateCreated : ourNewDate
        };

		if (slug) {
		    content_t["wp_slug"] = slug;
		}
		
        var argArray = [this.apiLink, this.blogID, this.username, this.password, content_t, aPublish];
        return performancingAPICalls.metaWeblog_newPost(argArray);
    };
    this.editPost = function (aPostid, aTitle, aDescription, aArrayOfCats, aDateCreated, aPublish, NOTUSED1, NOTUSED2, slug) {
        var ourNewDate = "";

        if(aDateCreated != ""){
           ourNewDate = new Date(aDateCreated)
        }
		
        var content_t =
        {
            title: aTitle,
            description: aDescription,
            dateCreated: ourNewDate,
            categories: aArrayOfCats
        };
		
		if (slug) {
		    content_t["wp_slug"] = slug;
		}
		
        var argArray = [this.apiLink, aPostid, this.username, this.password, content_t, aPublish];
        return performancingAPICalls.metaWeblog_editPost(argArray);
    };
    this.deletePost = function (aPostid) {
        var argArray = [this.apiLink, this.appKey, aPostid, this.username, this.password, 'bool1'];
        return performancingAPICalls.blogger_deletePost(argArray);
    };
	this.deletePage = function (pageId){
		return false;
	};
    this.getUsersBlogs = function () {
        var argArray = [this.apiLink, this.appKey, this.username, this.password];
        return performancingAPICalls.blogger_getUsersBlogs(argArray);
    };
    this.getRecentPosts = function () {
        var argArray = [this.apiLink, this.blogID, this.username, this.password, 20];
        return performancingAPICalls.metaWeblog_getRecentPosts(argArray);
        //return blogger_getRecentPosts(this.apiLink, this.appKey, this.blogID, this.username, this.password, aNumber);
    };
    /*
    metaWeblog.getCategories 
    metaWeblog.getCategories (blogid, username, password) returns struct
    The struct returned contains one struct for each category, containing the following elements: description, htmlUrl and rssUrl.
    This entry-point allows editing tools to offer category-routing as a feature.
    */
    this.getCategoryList = function () { //Not Available
        //return false;
        var argArray = [this.apiLink, this.blogID, this.username, this.password];
        return performancingAPICalls.metaWeblog_getCategoryList(argArray);
        
    };
    this.setPostCategories = function (aPostid, aCategories) { //Not Available
        //var argArray = [];
        return false;
    };
    this.publishPost = function (aPostid) {
        return false;
    };
    
    //metaWeblog.newMediaObject (blogid, username, password, struct)
    this.fileUpload = function (aFileName, aMimeType, aDataString) {
        var content_t =
        {
            name: aFileName,
            type: aMimeType,
            bits: aDataString.toString() //aBase64Data
        };
        var argArray = [this.apiLink, this.blogID, this.username, this.password, content_t];
        return performancingAPICalls.metaWeblog_newMediaObject(argArray);
    };
}
performancingMetaweblogAPI.prototype = new perFormancingBlogAPI();

var perFormancingMovableTypeAPI = function () {
	this.newPost = function (aTitle, aDescription, aArrayOfCats, aDateCreated, aPublish, tags, slug, custom_fields) {
		var ourNewDate = "";

        if(aDateCreated != ""){
           ourNewDate = new Date(aDateCreated)
        }
		
		var content_t = {
			title : aTitle,
			description : aDescription,
			categories : aArrayOfCats,
			mt_keywords : tags,
			dateCreated : ourNewDate
		};
		
		if (this.supportsCustomFields && custom_fields && custom_fields.length > 0) {
			content_t.custom_fields = custom_fields;
		}
		
		if (slug) {
		    content_t["wp_slug"] = slug;
		}
		
		var argArray = [this.apiLink, this.blogID, this.username, this.password, content_t, aPublish];
		return performancingAPICalls.metaWeblog_newPost(argArray);
	};
	
	this.newPage = function (aTitle, aDescription, aDateCreated, aPublish, slug, custom_fields) {
		var ourNewDate = "";

        if(aDateCreated != ""){
           ourNewDate = new Date(aDateCreated)
        }
		
		var content_t = {
			title : aTitle,
			description : aDescription,
			dateCreated : ourNewDate
		};
		
		if (this.supportsCustomFields && custom_fields && custom_fields.length > 0) {
			content_t.custom_fields = custom_fields;
		}
		
		if (slug) {
		    content_t["wp_slug"] = slug;
		}

		var argArray = [this.apiLink, this.blogID, this.username, this.password, content_t, aPublish];
		return performancingAPICalls.wp_newPage(argArray);
	};
	
	this.editPost = function (aPostid, aTitle, aDescription, aArrayOfCats, aDateCreated, aPublish, tags, NOTUSED, slug, custom_fields) {
		var ourNewDate = "";
		if (!tags) tags = "";
		if(aDateCreated != ""){
			ourNewDate = new Date(aDateCreated)
		}

		var content_t = {
			title: aTitle,
			description: aDescription,
			categories: aArrayOfCats,
			dateCreated: ourNewDate,
			mt_keywords : tags
		};
		
		if (this.supportsCustomFields && custom_fields && custom_fields.length > 0) {
			content_t.custom_fields = custom_fields;
		}
		
		if (slug) {
		    content_t["wp_slug"] = slug;
		}
		
		var argArray = [this.apiLink, aPostid, this.username, this.password, content_t, aPublish];
		return performancingAPICalls.metaWeblog_editPost(argArray);
	};
	
	this.deletePost = function (aPostid) {
		var argArray = [this.apiLink, this.appKey, aPostid, this.username, this.password, 1];
		return performancingAPICalls.blogger_deletePost(argArray);
	};
	
	this.deletePage = function (pageId) {
        var argArray = [this.apiLink, this.blogID, this.username, this.password, pageId, true];
        return performancingAPICalls.wp_deletePage(argArray);
	};
	
	this.getUsersBlogs = function () {
		if (SCRIBEFIRE_BLOG.type == "wordpress_cust") {
			// Wordpress gimped their implementation of blogger_getUsersBlogs because other clients were dumb.
			var argArray = [this.apiLink, this.username, this.password];
			return performancingAPICalls.wp_getUsersBlogs(argArray);
		}
		else {
			var argArray = [this.apiLink, this.appKey, this.username, this.password];
			return performancingAPICalls.blogger_getUsersBlogs(argArray);
		}
	};
	
	this.getRecentPosts = function () {
		var argArray = [this.apiLink, this.blogID, this.username, this.password, 30];
		return performancingAPICalls.metaWeblog_getRecentPosts(argArray);
	};
	
	this.getPages = function () {
		var argArray = [this.apiLink, this.blogID, this.username, this.password, 1000];
		return performancingAPICalls.wp_getPages(argArray);
	};
	
	this.getPageList = function () {
		var argArray = [this.apiLink, this.blogID, this.username, this.password];
		return performancingAPICalls.wp_getPageList(argArray);
	};
	
	this.getCategoryList = function () {
		var argArray = [this.apiLink, this.blogID, this.username, this.password];
		return performancingAPICalls.mt_getCategoryList(argArray);
	};
	
	this.newCategory = function (aCategory) {
		var argArray = [this.apiLink, this.blogID, this.username, this.password, { name : aCategory} ];
		return performancingAPICalls.wp_newCategory(argArray);
	};
	
	this.setPostCategories = function (aPostid, aCategories) {
		var argArray = [this.apiLink, aPostid, this.username, this.password, aCategories];
		return performancingAPICalls.mt_setPostCategories(argArray);
	};

	this.getPostCategories = function (aPostid) {
		var argArray = [this.apiLink, aPostid, this.username, this.password];
		return performancingAPICalls.mt_getPostCategories(argArray);
	};

	this.publishPost = function (aPostid) {
		var argArray = [this.apiLink, aPostid, this.username, this.password];
		return performancingAPICalls.mt_publishPost(argArray);
	};

	this.fileUpload = function (aFileName, aMimeType, aDataString) {
		var content_t = {
			name: aFileName,
			type: aMimeType,
			bits: aDataString.toString()
		};
		
		var argArray = [this.apiLink, this.blogID, this.username, this.password, content_t];
		return performancingAPICalls.metaWeblog_newMediaObject(argArray);
	};
	
	this.supportsPages = true;
	this.supportsCustomFields = true;
	this.supportsTags = true;
};

perFormancingMovableTypeAPI.prototype = new perFormancingBlogAPI();

var perFormancingAtomAPI = function () {
    this.newPost = function (aTitle, aDescription, aArrayOfCats, aDateCreated, aPublish) {
        var J = new perFormancingAtomAPIObject();
        J.init2(this.apiLink, this.username, this.password);
        J.newPost(aTitle, aDescription, aDateCreated, aPublish);
    };
    this.editPost = function (aPostid, aTitle, aDescription, aArrayOfCats, aDateCreated, aPublish, aEditURI, aAtomID) {
        var J = new perFormancingAtomAPIObject();
        J.init2(this.apiLink, this.username, this.password);
        J.editPost(aPostid, aTitle, aDescription, aDateCreated, aPublish, aEditURI, aAtomID);
    };
    this.deletePost = function (aPostid, aEditURI) {
        var J = new perFormancingAtomAPIObject();
        J.init2(this.apiLink, this.username, this.password);
        J.deletePost(aPostid, aEditURI);
    };
    this.getUsersBlogs = function () {
        var J = new perFormancingAtomAPIObject();
        J.init2(this.apiLink, this.username, this.password);
        J.getUsersBlogs();
    };
    this.getRecentPosts = function () {
        var J = new perFormancingAtomAPIObject();
        J.init2(this.apiLink, this.username, this.password);
        J.getRecentPosts();
    };
    this.getCategoryList = function () {
        //aListener.onResult(null);
        return false;
    };
    this.setPostCategories = function (aPostid, aCategories) {
        //aListener.onResult(null);
        return false;
    };
    
    this.publishPost = function (aPostid) {
         return false;
    };
	
	this.deletePage = function () {
		return false;
	};
}
perFormancingAtomAPI.prototype = new perFormancingBlogAPI();

//BLOGGER BETA
var perFormancingBloggerAtomAPI = function () {
    this.theObject = new perFormancingBloggerAtomAPIObject();
    this.theObject.authToken = null;
    this.theObject.isLoggedIn = null;
    
	this.staticCategories = [];

    this.newPost = function (aTitle, aDescription, aArrayOfCats, aDateCreated, aPublish) {
		// Does not support dateCreated
        this.theObject.init2(this.apiLink, this.username, this.password);
        this.theObject.newPost(aTitle, aDescription, aDateCreated, aPublish);
    };
    this.editPost = function (aPostid, aTitle, aDescription, aArrayOfCats, aDateCreated, aPublish, aEditURI, aAtomID, forODS) {
		// Does not support dateCreated
        this.theObject.init2(this.apiLink, this.username, this.password);
        this.theObject.editPost(aPostid, aTitle, aDescription, aDateCreated, aPublish, aEditURI, aAtomID, forODS);
    };
    this.deletePost = function (aPostid, aEditURI) {
        this.theObject.init2(this.apiLink, this.username, this.password);
        this.theObject.deletePost(aPostid, aEditURI);
    };
    this.getUsersBlogs = function () {
        this.theObject.init2(this.apiLink, this.username, this.password);
        this.theObject.getUsersBlogs();
    };
    this.getRecentPosts = function (aNumber, forODS, type) {
        this.theObject.init2(this.apiLink, this.username, this.password);
        this.theObject.getRecentPosts(50, forODS, type);
    };

	this.aggregateCategories = function (catArray) {
		add : for (var i = 0; i < catArray.length; i++) {
			find : for (var j = 0; j < this.staticCategories.length; j++) {
				if (this.staticCategories[j].categoryName == catArray[i]) {
					continue add;
				}
			}
			
			this.staticCategories.push({ "categoryName" : catArray[i], "categoryId" : catArray[i] });
		}
	},

    this.getCategoryList = function () {
        return this.staticCategories;
    };
    this.setPostCategories = function (aPostid, aCategories) {
        return false;
    };
    this.publishPost = function (aPostid) {
         return false;
    };
    this.doAuth = function () {
        this.theObject.init2(this.apiLink, this.username, this.password);
        this.theObject.doAuth();
    };
    this.doSetup = function () {
        this.theObject.doSetup();
    };
    
	this.deletePage = function () {
		return false;
	};
	
    this.addCategories = true;
}
perFormancingBloggerAtomAPI.prototype = new perFormancingBlogAPI();


var performancingTumblrAPI = function () {
	this.supportsDrafts = false;
	
	this.extraOptions = {
		"private": {
			"type" : "checkbox",
			"label" : "Private post"
		}
	};	
	
	this.login = function (successCallback, failureCallback) {
		var url = "http://www.tumblr.com/api/authenticate";
		
		var args = {};
		args.email = this.username;
		args.password = this.password;
		
		var argstring = "";
		
		for (var i in args) {
			argstring += encodeURIComponent(i) + "=" + encodeURIComponent(args[i]) + "&";
		}
		
		argstring = argstring.substr(0, argstring.length - 1);
		
		var req = new XMLHttpRequest();
		req.open("POST", url, true);
		req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		req.setRequestHeader("Content-Length", argstring.length);
		
		req.onreadystatechange = function () {
			try {
				if (req.readyState == 4) {
					if (req.status == 200) {
						successCallback(req.responseText, req.responseXML);
					}
					else {
						failureCallback();
					}
				}
			} catch (e) {
				alert(e);
				failureCallback();
			}
		};
		
		req.send(argstring);
	};
	
    this.newPost = function (aTitle, aDescription, aArrayOfCats, aDateCreated, notUsed, aTags, notUsed2, notUsed3, extra_options) {
		var args = {};
		args.email = this.username;
		args.password = this.password;
		args.generator = "ScribeFire";
		args.group = SCRIBEFIRE_BLOG.url.split("//")[1].split("/")[0];
		
		if ("private" in extra_options) {
			args["private"] = extra_options["private"] * 1;
		}
		
		var theDate = new Date(aDateCreated);
		var now = new Date();
		
		if (theDate > now) {
			aDateCreated = now;
		}
		else {
			aDateCreated = theDate;
		}
		
		args.date = aDateCreated.toString();
		args.tags = aTags;
		args.type = 'regular';
		args.format = 'html';
		args.title = aTitle;
		args.body = aDescription;

		var argstring = "";
		
		for (var i in args) {
			argstring += encodeURIComponent(i) + "=" + encodeURIComponent(args[i]) + "&";
		}
		
		argstring = argstring.substr(0, argstring.length - 1);
		
		var req = new XMLHttpRequest();
		req.open("POST", "http://www.tumblr.com/api/write", true);
		req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		req.setRequestHeader("Content-Length", argstring.length);

		req.onreadystatechange = function (event) {
			if (req.readyState == 4) {
				if (req.status == 201) {
					// No problem.
					performancing_xmlcall.processReturnData({ }, 'newpostcall', null, true, null, null);
				}
				else {
					// TODO posting error
					alert(req.responseText);
				}
			}
		};
		
		req.send(argstring);
	};
	
    this.editPost = function (aPostid, aTitle, aDescription, aArrayOfCats, aDateCreated, aPublish, aTags, aAtomID, forODS, notUsed, extra_options) {
        var args = {};
		args.email = this.username;
		args.password = this.password;
		args.generator = "ScribeFire";
		
		var theDate = new Date(aDateCreated);
		var now = new Date();
		
		if (theDate > now) {
			aDateCreated = now;
		}
		else {
			aDateCreated = theDate;
		}
		
		args.date = aDateCreated.toString();
		args.tags = aTags;
		args.title = aTitle;
		args.body = aDescription;
        args["post-id"] = aPostid;
		
		if ("private" in extra_options) {
			args["private"] = extra_options["private"] * 1;
		}

		var argstring = "";
		
		for (var i in args) {
			argstring += encodeURIComponent(i) + "=" + encodeURIComponent(args[i]) + "&";
		}
		
		argstring = argstring.substr(0, argstring.length - 1);
		
		var req = new XMLHttpRequest();
		req.open("POST", "http://www.tumblr.com/api/write", true);
		req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		req.setRequestHeader("Content-Length", argstring.length);

		req.onreadystatechange = function (event) {
			if (req.readyState == 4) {
				if (req.status == 201) {
					// No problem.
					performancing_xmlcall.processReturnData({ }, 'editpostcall', null, true, null, null);
				}
				else {
					// TODO posting error
					alert(req.responseText);
				}
			}
		};
		
		req.send(argstring);
    };

	this.deletePost = function (aPostid) {
	    var args = {};
		args.email = this.username;
		args.password = this.password;
        args["post-id"] = aPostid;
        
		var argstring = "";
		
		for (var i in args) {
			argstring += encodeURIComponent(i) + "=" + encodeURIComponent(args[i]) + "&";
		}
		
		argstring = argstring.substr(0, argstring.length - 1);
		
		var req = new XMLHttpRequest();
		req.open("POST", "http://www.tumblr.com/api/delete", true);
		req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		req.setRequestHeader("Content-Length", argstring.length);

		req.onreadystatechange = function (event) {
			if (req.readyState == 4) {
				if (req.status == 201) {
					// No problem.
					performancing_xmlcall.processReturnData(null, 'deletehistorycall', null, true);
				}
				else {
					// TODO posting error
					alert(req.responseText);
				}
			}
		};
		
		req.send(argstring);
    };

    this.getUsersBlogs = function (blogUrl) {
		function callback(text, xml) {
			var blogs = [];
			
			var blogNodes = xml.getElementsByTagName("tumblelog");
			
			for (var i = 0; i < blogNodes.length; i++) {
				blogs.push( { blogName : blogNodes[i].getAttribute("title"), blogid : i, url : blogNodes[i].getAttribute("url") } );
			}

	        performancing_xmlcall.processData(blogs, null, 'accountwizard', "", true);
		}
	
		this.login(callback, this.loginFailed);
    };

	this.loginFailed = function () {
		alert(performancingUI.getLocaleString("tumblrLoginFailed"));
	};

	this.populateHistoryList = function () {
		var url = SCRIBEFIRE_BLOG.url + "api/read/json?start=0&num=50&type=regular";
		
		var req = new XMLHttpRequest();
		req.open("GET", url, true);
		
		req.onreadystatechange = function () {
			if (req.readyState == 4) {
			    var jsonString = req.responseText;
			    
			    // Get rid of the variable assignment, since callback= doesn't work.
			    jsonString = jsonString.replace("var tumblr_api_read = ", "");
			    jsonString = jsonString.replace("};", "}");
                
			    var json = SCRIBEFIRE_JSON.fromString(jsonString);
				
				var rv = [];
				
				for (var i = 0; i < json.posts.length; i++) {
					var entryObject = { 'title' : json.posts[i]["regular-title"], 'description' : json.posts[i]["regular-body"], 'dateCreated' : json.posts[i]["date-gmt"], 'postid' : json.posts[i].id, 'tags' : "", 'permaLink': json.posts[i].url };
					
					try {
						var tags = json.posts[i]["tags"].join(", ");
						entryObject.tags = tags;
					} catch (noTags) { }
					
					rv.push(entryObject);
				}
				
				performancing_xmlcall.processData(rv, null, 'historycall', "", true);
			}
		};
		
		req.send(null);
	};

	this.populateCategoryChecklist = function () {
		var categories = [];
		
		performancing_xmlcall.processReturnData(categories, 'categorycall');
	};
    
    this.addCategories = false;
	this.standard = false;
	this.supportsTags = true;
};

performancingTumblrAPI.prototype = new perFormancingBlogAPI();

var performancingPosterousAPI = function () {
	this.supportsDrafts = false;
	this.addCategories = false;
	this.standard = false;
	this.supportsTags = true;
	
	this.extraOptions = {
		"autopost" : {
			"type": "checkbox",
			"label": "Autopost"
		},
		
		"private": {
			"type" : "checkbox",
			"label" : "Private post"
		}
	};
	
	this.getUsersBlogs = function () {
		var url = "http://posterous.com/api/getsites";
		
		var req = new XMLHttpRequest();
		req.open("POST", url, true);
		req.setRequestHeader("Authorization", "Basic " + btoa(this.username + ":" + this.password));
		
		req.onreadystatechange = function () {
			try {
				if (req.readyState == 4) {
					if (req.status == 200) {
						var xml = req.responseXML;
						var sites = xml.getElementsByTagName("site");
						var blogs = [];
						
						for (var i = 0; i < sites.length; i++) {
							blogs.push( { blogName : sites[i].getElementsByTagName("name")[0].textContent, blogid : sites[i].getElementsByTagName("id")[0].textContent, url : sites[i].getElementsByTagName("url")[0].textContent } );
						}
						
						performancing_xmlcall.processData(blogs, null, 'accountwizard', "", true);
					}
					else {
						alert("login failed");
					}
				}
			} catch (e) {
				alert(e);
				alert("login failed");
			}
		};
		
		req.send(null);
	};
	
    this.newPost = function (aTitle, aDescription, aArrayOfCats, aDateCreated, notUsed, aTags, notUsed1, notUsed2, extra_options) {
		var args = {};
		args.site_id = SCRIBEFIRE_BLOG.blogId;
		args.title = aTitle;
		args.body = aDescription;
		args.tags = aTags;
		
		if ("private" in extra_options) {
			args.private = extra_options["private"] * 1;
		}
		
		if ("autopost" in extra_options) {
			args.autopost = extra_options["autopost"] * 1;
		}
		
		args.source = "ScribeFire";
		args.sourceLink = "http://www.scribefire.com/";
		
		var media = performancingEditor.getMedia();
		
		// media is now an array of file paths
	
		for (var i = 0; i < media.length; i++) {
			var ios = Components.classes["@mozilla.org/network/io-service;1"]. getService(Components.interfaces.nsIIOService);  
			var url = ios.newURI(media[i], null, null);  
			var theFile = url.QueryInterface(Components.interfaces.nsIFileURL).file;
			
			args["media["+i+"]"] = {
				"file" : theFile,
			};
		}
		
		var postRequest = createPostRequest(args);
		
		var url = "http://posterous.com/api/newpost";
		
		var req = new XMLHttpRequest();
		req.open("POST", url, true);
		req.setRequestHeader("Authorization", "Basic " + btoa(this.username + ":" + this.password));
		req.setRequestHeader("Content-Length", (postRequest.requestBody.available()));
		req.setRequestHeader("Content-Type","multipart/form-data; boundary="+postRequest.boundary);
		
		req.onreadystatechange = function () {
			try {
				if (req.readyState == 4) {
					if (req.status == 200) {
						performancing_xmlcall.processReturnData({ }, 'newpostcall', null, true, null, null);
					}
					else {
						var xml = req.responseXML;
						var msg = xml.getElementsByTagName("err")[0].getAttribute("msg");
						alert("Failure to post to Posterous: " + msg);
					}
				}
			} catch (e) {
				alert("Failed to communicate with Posterous: " + e);
			}
		};
		
		req.send(postRequest.requestBody);
	};
	
    this.editPost = function (aPostid, aTitle, aDescription, aArrayOfCats, aDateCreated, aPublish, aTags, aAtomID, forODS, notUsed, extra_options) {
		var args = {};
		args.post_id = aPostid;
		args.title = aTitle;
		args.body = aDescription;
		
		var media = performancingEditor.getMedia();
		
		// media is now an array of file paths
	
		for (var i = 0; i < media.length; i++) {
			var ios = Components.classes["@mozilla.org/network/io-service;1"]. getService(Components.interfaces.nsIIOService);  
			var url = ios.newURI(media[i], null, null);  
			var theFile = url.QueryInterface(Components.interfaces.nsIFileURL).file;
			
			args["media["+i+"]"] = {
				"file" : theFile,
			};
		}
		
		var postRequest = createPostRequest(args);
		
		var url = "http://posterous.com/api/updatepost";
		
		var req = new XMLHttpRequest();
		req.open("POST", url, true);
		req.setRequestHeader("Authorization", "Basic " + btoa(this.username + ":" + this.password));
		req.setRequestHeader("Content-Length", (postRequest.requestBody.available()));
		req.setRequestHeader("Content-Type","multipart/form-data; boundary="+postRequest.boundary);

		req.onreadystatechange = function () {
			try {
				if (req.readyState == 4) {
					if (req.status == 200) {
						performancing_xmlcall.processReturnData({ }, 'editpostcall', null, true, null, null);
					}
					else {
						var xml = req.responseXML;
						var msg = xml.getElementsByTagName("err")[0].getAttribute("msg");
						alert("Failure to post to Posterous: " + msg);
					}
				}
			} catch (e) {
				alert("Failed to communicate with Posterous: " + e);
			}
		};
		
		req.send(postRequest.requestBody);
    };

	this.deletePost = function (aPostid) {
		alert("Posterous does not support deleting posts at this time.");
    };

	this.populateHistoryList = function () {
		var url = "http://posterous.com/api/readposts";
		
		var args = {};
		args.site_id = SCRIBEFIRE_BLOG.blogId;
		args.num_posts = 50;
		
		var argstring = "";

		for (var i in args) {
			argstring += encodeURIComponent(i) + "=" + encodeURIComponent(args[i]) + "&";
		}

		argstring = argstring.substr(0, argstring.length - 1);
		
		var req = new XMLHttpRequest();
		req.open("POST", url, true);
		req.setRequestHeader("Authorization", "Basic " + btoa(this.username + ":" + this.password));
		req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		req.setRequestHeader("Content-Length", argstring.length);
		
		req.onreadystatechange = function () {
			if (req.readyState == 4) {
				if (req.status == 200) {
					var xml = req.responseXML;
					var posts = xml.getElementsByTagName("post");
				
					var rv = [];
				
					for (var i = 0; i < posts.length; i++) {
						var entryObject = {};
					
						entryObject.title = posts[i].getElementsByTagName("title")[0].textContent;
						entryObject.description = posts[i].getElementsByTagName("body")[0].textContent;
						entryObject.dateCreated = posts[i].getElementsByTagName("date")[0].textContent;
						entryObject.postid = posts[i].getElementsByTagName("id")[0].textContent;
						entryObject.tags = "";
						entryObject.permaLink = posts[i].getElementsByTagName("link")[0].textContent;
						
						rv.push(entryObject);
					}
				
					performancing_xmlcall.processData(rv, null, 'historycall', "", true);
				}
			}
		};
		
		req.send(argstring);
	};
	
	this.handleFileUpload = function (file) {
		performancingEditor.insertText('<img src="file://' + file.path + '" />');
	};
	
	this.prepContent = function (doc) {
		var images = doc.getElementsByTagName("img");
		
		var shownAlert = false;
		
		if (images.length > 0) {
			for (var i = images.length - 1; i >= 0; i--) {
				if (images[i].getAttribute("src").match(/^file:/)) {
					performancingEditor.addMedia(images[i].getAttribute("src"));
					images[i].parentNode.removeChild(images[i]);
				}
			}
			
			var theDocument = performancingEditor.getCurrentEditorDocument();
			var tabbox = theDocument.getElementById("performancing-editor-tabbox");
			
			if (tabbox.selectedIndex == 1) {
				performancingEditor.getCurrentEditorWindow().performancingMidas.syncSourceTab();
			}
		}
		
		return doc;
	};
		
	this.populateCategoryChecklist = function () {
		performancing_xmlcall.processReturnData([], 'categorycall');
	};
};

performancingPosterousAPI.prototype = new perFormancingBlogAPI();

var performancingAPICalls = new Object();

performancingAPICalls = {
    //myParams  = [url, appkey, blogid, username, password, content, publish]
    blogger_newPost: function(myParams) {
      return bfXMLRPC.makeXML("blogger.newPost", myParams);
    },
    
    //myParams  = [url, appkey, postid, username, password, content, publish]
    blogger_editPost: function(myParams) {
      return bfXMLRPC.makeXML("blogger.editPost", myParams);
    },
    
    //myParams  = [url, appkey, postid, username, password, publish]
    blogger_deletePost: function(myParams) {
      return bfXMLRPC.makeXML("blogger.deletePost", myParams);
    },
    
    //myParams  = [url, appkey, blogid, username, password, numberOfPosts]
    blogger_getRecentPosts: function(myParams) {
      return bfXMLRPC.makeXML("blogger.getRecentPosts", myParams);
    },
    
    //myParams  = [url, appkey, username, password]
    blogger_getUsersBlogs: function(myParams) {
      return bfXMLRPC.makeXML("blogger.getUsersBlogs", myParams);
    },
    
    //myParams  = [url, appkey, username, password]
    blogger_getUserInfo: function(myParams) {
      return bfXMLRPC.makeXML("blogger.getUserInfo", myParams);
    },
    
    //myParams  = [url, blogid, username, password, content_t, publish]
    metaWeblog_newPost: function(myParams) {
		return bfXMLRPC.makeXML("metaWeblog.newPost", myParams);
    },
    
    metaWeblog_editPost: function(myParams) {
      return bfXMLRPC.makeXML("metaWeblog.editPost", myParams);
    },
    
    //myParams  = [url, blogid, username, password, numberOfPosts]
    metaWeblog_getRecentPosts: function(myParams) {
      return bfXMLRPC.makeXML("metaWeblog.getRecentPosts", myParams);
    },
    
    //myParams  = [url, blogid, username, password]
    metaWeblog_getCategoryList: function(myParams) {
      return bfXMLRPC.makeXML("metaWeblog.getCategories", myParams);
    },
    
    //myParams  = [url, blogid, username, password, mediaStruct]
    metaWeblog_newMediaObject: function(myParams) {
      return bfXMLRPC.makeXML("metaWeblog.newMediaObject", myParams);
    },
    
    //myParams  = [url, blogid, username, password, numberOfPosts]
    mt_getRecentPostTitles: function(myParams) {
      return bfXMLRPC.makeXML("mt.getRecentPostTitles", myParams);
    },
    
    //myParams  = [url, blogid, username, password]
    mt_getCategoryList: function(myParams) {
      return bfXMLRPC.makeXML("mt.getCategoryList", myParams);
    },
    
    //myParams  = [url, postid, username, password, categories]
    mt_setPostCategories: function(myParams) {
      return bfXMLRPC.makeXML("mt.setPostCategories", myParams);
    },

	mt_getPostCategories: function(myParams) {
		return bfXMLRPC.makeXML("mt.getPostCategories", myParams);
	},
	
    //mt_publishPost
    //myParams  = [url, postid, username, password]
    mt_publishPost: function(myParams) {
      return bfXMLRPC.makeXML("mt.publishPost", myParams);
    },
	
	wp_getPage : function (myParams) {
		return bfXMLRPC.makeXML("wp.getPage", myParams);
	},
	wp_getPages : function (myParams) {
		//	    $blog_id    = $args[0];
		//      $username    = $args[1];
		//      $password    = $args[2];
		return bfXMLRPC.makeXML("wp.getPages", myParams);
	},
	wp_newPage : function (myParams) {
		return bfXMLRPC.makeXML("wp.newPage", myParams);
	},
	wp_deletePage : function (myParams) {
		return bfXMLRPC.makeXML("wp.deletePage", myParams);
	},
	wp_editPage : function (myParams) {
		return bfXMLRPC.makeXML("wp.editPage", myParams);
	},
	wp_getPageList : function (myParams) {
		return bfXMLRPC.makeXML("wp.getPageList", myParams);
	},
	wp_getAuthors : function (myParams) {
		return bfXMLRPC.makeXML("wp.getAuthors", myParams);
	},
	wp_newCategory : function (myParams) {
		return bfXMLRPC.makeXML("wp.newCategory", myParams);
	},
	wp_suggestCategories : function (myParams) {
		return bfXMLRPC.makeXML("wp.suggestCategories", myParams);
	},
	wp_getUsersBlogs : function (myParams) {
		return bfXMLRPC.makeXML("wp.getUsersBlogs", myParams);
	}
}

function perFormancingAtomAPIObject() {
}

perFormancingAtomAPIObject.prototype = {
    _req: null,
    _url: null,

    ERROR_HTTP:   10,
    ERROR_FAULT:   11,
    ERROR_PARSER:   12,

    init2: function(aUrl, aUsername, aPassword) {
        this._url = aUrl;
        this._user = aUsername;
        this._pass = aPassword;
    },

    doRequest: function( method, url, body, processor) {
		alert(performancingUI.getLocaleString("reAddBlogger"));
    },

    getRecentPosts: function() {
        //var url = this._url; 
        //url.match(/(.+\/)(.+)/);
        //if(RegExp.$2=="post") {
        //    url = RegExp.$1 + "feed";
        //}
        this.doRequest("GET", this._url, null, this.parseRecentPosts);
        return true;
    },
    getUsersBlogs: function() {
        this.doRequest("GET", this._url, null, this.parseUsersBlogs);
    },

    parseUsersBlogs: function( inst) {
        try {
            var rval = new Array();
            var dom = inst._req.responseXML;
            var links = dom.getElementsByTagName("link");
            for(var i=0;i<links.length;++i)
            {
                var link = links[i];
                var title = link.getAttribute("title");
                var rel = link.getAttribute("rel");
                var href = link.getAttribute("href");
                if(rel!="service.post") continue;

                href.match(/.+\/(.+)/);
                var bid = RegExp.$1;

                var obj  =
                {
                    blogName: title,
                    blogid:  bid,
                    url:  href
                };
                rval[rval.length++] = obj;
            }
            //listener.onResult(rval);
            performancing_xmlcall.processData(rval, null, 'accountwizard', "", true);
        }
        catch(e) {
        }
    },

    parseRecentPosts: function( inst) {
        //dump("\n\n parseRecentPosts ATOM \n\n");
        var rval = new Array();
        var dom = inst._req.responseXML;
        var entries = dom.getElementsByTagName("entry");
        for(var i=0;i<entries.length;++i)
        {
            try
            {
                var entry_n = entries[i];
                var content_n = inst.getNamedChild(entry_n, "content");
                var title_n = inst.getNamedChild(entry_n, "title");
                var created_n = inst.getNamedChild(entry_n, "issued");
                var author_n = inst.getNamedChild(entry_n, "author");
                var link_n = null;
                var atomid_n = inst.getNamedChild(entry_n, "id");
                var atomid = "";
                if(atomid_n) atomid = atomid_n.firstChild.nodeValue;

                for(var j=0;j<entry_n.childNodes.length;++j) {
                    if(entry_n.childNodes[j].nodeName=="link") {
                        var tmp = entry_n.childNodes[j];
                        if(tmp.getAttribute("rel").match(/edit/)) {
                            link_n = tmp;
                        }
                    }
                }

                var href = link_n.getAttribute("href");
                href.match(/.+\/(.+)/);
                var postid = RegExp.$1;

                var dateval = created_n.firstChild.nodeValue;
                //var date = flock_parseDate(dateval);
                var val = dateval;
                var dateutc =  Date.UTC(val.slice(0, 4), val.slice(4, 6) - 1, 
                        val.slice(6, 8), val.slice(9, 11), val.slice(12, 14), 
                        val.slice(15));
                var date =  new Date(dateutc);

                var xs = new XMLSerializer();

                var data = "";
                if(content_n) {
                    for(var j=0;j<content_n.childNodes.length;++j) {
                        data += xs.serializeToString(content_n.childNodes.item(j));
                    }
                }
                data = data.replace(/&lt;/g,"<");
                data = data.replace(/&gt;/g,">");
                data = data.replace(/&quot;/g,"\"");
                data = data.replace(/&amp;/g,"&");

                var obj  =
                {
                    description: data,
                    title: title_n.firstChild.nodeValue,
                    dateCreated: date,
                    postid:  postid,
                    editURI:  href,
                    atomid:  atomid
                };
                rval[rval.length] = obj;
            }
            catch(e)
            {
            }
        }
        //listener.onResult(rval);
        //dump("\n\n parseRecentPosts ATOM Finished \n\n");
        performancing_xmlcall.processData(rval, null, 'historycall', "", true);
    },
    getNamedChild: function(node, name) {
        for (var i = 0; i < node.childNodes.length; i++) {
            if(node.childNodes[i].nodeName==name) return node.childNodes[i];
        }
        return null;
    },
    deletePost: function ( postid, aEditURI) {
        var url = this._url;
        if(postid) url += "/" + postid;
        if(aEditURI) url = aEditURI;
        this.doRequest("DELETE", url,null, this.handleDelete);
    },
    doPost: function ( method, postid, title, description, date_created, doPublish, aEditURI, aAtomID, isEdit) {

        var url = this._url;
        if(postid) url += "/" + postid;

        //if(aEditURI) url += "/" + aEditURI;

        //var date = bfXMLRPC.iso8601Format(date_created);
        var date = "";
        try{
            date = bfXMLRPC.iso8601Format(date_created);
        }catch(e){
            //foo
        }

        var body = "";
        body += '<?xml version="1.0" encoding="UTF-8" ?>';
        body += '<entry xmlns="http://purl.org/atom/ns#">';

        var draft = "false";
        if(doPublish == false || doPublish == 'bool0') draft = "true";
        
		var useEntities = true;
            var entity_description = "";
            for (var desc_i=0; desc_i < description.length; desc_i++){
                entity_description += "&#" + description.charCodeAt(desc_i) + ";";
            }
        
            var entity_title = "";
            for (var title_i=0; title_i < title.length; title_i++){
                entity_title += "&#" + title.charCodeAt(title_i) + ";";
            }
            
            description = entity_description;
            title = entity_title;
            body += '  <title type="text/plain" mode="escaped">' + title + '</title>';
            body += '  <issued>' + date + '</issued>';
            body += '  <generator url="http://www.scribefire.com/">ScribeFire</generator>';
            body += '  <content type="text/plain" mode="escaped">' + description + '</content>';
            body += '  <draft xmlns="http://purl.org/atom-blog/ns#">' + draft + '</draft> ';
            body += '</entry>';
        
        dump("\n\n********** \nDescription: " + description +"\n\n********** \title: "+ title);
        //dump(body);
        this.doRequest(method,url,body,this.parsePosts, doPublish);
    },
    editPost: function ( postid, title, description, date_created, isDraft, aEditURI, aAtomID) {
        this.doPost( "PUT", postid, title, description, date_created, isDraft, aEditURI, aAtomID, "isEdit");
    },
    newPost: function ( title, description, date_created, isDraft) {
        this.doPost( "POST", null, title, description, date_created, isDraft);
    },
    parsePosts: function(inst) {
        var dom = inst._req.responseXML;

        if(!dom) {
            // LiveJournal - everone wants to be different, don't they?
            if(inst._req.responseText.match(/OK/)) {
                performancing_xmlcall.processData(1, null, null, "", true);
                return;
            }
            else {
				alert(performancingUI.getLocaleString("reAddBlogger"));
                return;
            }
        }

        var entries = dom.getElementsByTagName("entry");

		if (!entries || entries.length == 0) {
			alert("The server did not return the expected data:\n\n" + inst_.req.responseText);
			return;
		}

        var rval = new Object();

        try {
            var entry_n = entries[0];
            var link_n = null;
            var perm_link_n = null;
            var atomid_n = inst.getNamedChild(entry_n, "id");
            var atomid = "";
            if(atomid_n) atomid = atomid_n.firstChild.nodeValue;
            for(var j=0;j<entry_n.childNodes.length;++j) {
                if(entry_n.childNodes[j].nodeName=="link") {
                    var tmp = entry_n.childNodes[j];
                    if(tmp.getAttribute("rel").match(/edit/)) {
                        link_n = tmp;
                    }
                    else if(tmp.getAttribute("rel").match(/alternate/)) {
                        perm_link_n = tmp;
                    }
                }
            }
            var href = link_n.getAttribute("href");
            rval.editURI = href;
            rval.atomid = atomid;
            href.match(/.+\/(.+)/);
            rval.uid = RegExp.$1;;
            //Livejournal hackage
            if(rval.editURI.length>0 && rval.atomid.length==0) {
                var perm_link = perm_link_n.getAttribute("href");
                if(perm_link.match(/livejournal/)) {
                    perm_link.match(/.+livejournal.com\/users\/(.+?)\/(.+?)\./);
                    rval.atomid = "urn:lj:livejournal.com:atom1:" + RegExp.$1 + ":" + RegExp.$2;
                }
            }
        }
        catch(e)
        {
            var localeString = "An error occurred:\n\n" + e.toSource() + "\n\n" + inst._req.responseText;
            alert(localeString);
        }
        performancing_xmlcall.processData(rval, null, 'newpostcall', "", true );
        //performancing_xmlcall.processData(rval, 'historycall', null, true);
    },
    
    handleDelete: function( inst) {
        //listener.onResult(1);
        performancing_xmlcall.processData(1, null, 'deletehistorycall', "", true);
    }
}

/*
    Blogger Beta
    -------------------
    GET "http://beta.blogger.com/feeds/214142430004041626/posts/full"
    
    //URL
    theLinks = theGood.getElementsByTagName("link")
    for(i in theLinks){
        if(theLinks[i].getAttribute("rel") == "alternate"){
                 alert(theLinks[i].getAttribute("href") ); 
                 break;
        }
    }
    
    //Title
    theTitles = theGood.getElementsByTagName("title");
    theTitles[0].firstChild.nodeValue;
    
    //ID
    theIDs = theGood.getElementsByTagName("id");
    theIDs[0].firstChild.nodeValue;
*/
function perFormancingBloggerAtomAPIObject() {
}
var pffGoogleAuth = "";
var pffGoogleAuthIsLoggedin = false;

perFormancingBloggerAtomAPIObject.prototype= {
    titleRegExp: /(?:\<title\stype\=\'\w*\'\>)([\s\S\s]*)(?=\<\/title\>)/,
    getFullIDRegExp: /(?:\<id\>)(\S*)(?=\<\/id\>)/,
    urlRegExp: /(?:\<link\srel\=\'\w*\'\stype\=\'[\w\W]*\'\shref\=\')([\s\S\s]*)(?=\<\/link>)/,
    
    idRegexp: /(?:[\S]*feeds\/)([\d]*)(?=\/posts)/,
    postIDRegexp: /(?:[\S]*posts\/full\/)([\d]*)(?=\")/,
    
    _req: null,
    _url: null,

    ERROR_HTTP:   10,
    ERROR_FAULT:   11,
    ERROR_PARSER:   12,
    
    init2: function( aUrl, aUsername, aPassword) {
        this._url = aUrl;
        this._user = aUsername;
        this._pass = aPassword;
    },
    
    doSetup: function( aUrl, aUsername, aPassword) {
        pffGoogleAuth = "";
        pffGoogleAuthIsLoggedin = false;
    },
    
	doBlockingAuth : function () {
		var theUA = "scribefire";
		var theMsg = "Email="+this._user+"&Passwd="+encodeURIComponent(this._pass)+"&service=blogger&source="+theUA;
		var theGood = null; 
		var theObject = this;

		var req = new XMLHttpRequest();
		req.open("POST", "https://www.google.com/accounts/ClientLogin", false);
		req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		req.setRequestHeader("Content-Length", theMsg.length);

		req.send(theMsg);

		if (req.status == 200) {
			theGood = req.responseText;
			theAuth = theGood.match(/(?:Auth\=)(.*)/);
			pffGoogleAuth = theAuth[1];
			pffGoogleAuthIsLoggedin = true;
		}
		else {
			try {
				var errorType = req.responseText.split('=')[1].replace(/\s*$/,""); 
				var errorMessage = '';

				switch (errorType) {
					case 'BadAuthentication':
						errorMessage = performancingUI.getLocaleString('errors.blogger.badauthentication');
					break;
					case 'NotVerified':
						errorMessage = performancingUI.getLocaleString('errors.blogger.notverified');
					break;
					case 'TermsNotAgreed':
						errorMessage = performancingUI.getLocaleString('errors.blogger.termsnotagreed');
					break;
					case 'AccountDeleted':
						errorMessage = performancingUI.getLocaleString('errors.blogger.accountdeleted');
					break;
					case 'ServiceDisabled':
						errorMessage = performancingUI.getLocaleString('errors.blogger.servicedisabled');
					break;
					case 'ServiceUnavailable':
						errorMessage = performancingUI.getLocaleString('errors.blogger.serviceunavailable');
					break;
					case 'Unknown':
					default:
						errorMessage = performancingUI.getLocaleString('errors.blogger.unknown');
					break;
				}

				alert(errorMessage);
			
			} catch (e) {
				alert(performancingUI.getLocaleString("upload.error.googleError", [ theCall.request.responseText ]));
			}
		}
	},

    doAuth: function(processor, forODS, type) {
        if(!pffGoogleAuthIsLoggedin){
            var theUA = "scribefire";
            var theMsg = "Email="+this._user+"&Passwd="+encodeURIComponent(this._pass)+"&service=blogger&source="+theUA;
            var theCall = new PffXmlHttpReq("https://www.google.com/accounts/ClientLogin", "POST", theMsg, false, null, null);
            var theGood = null; 
            var theProcessor = processor;
            var theObject = this;

            theCall.onResult = function( aText, aXML ){ 
                theGood = aText;
                theAuth = theGood.match(/(?:Auth\=)(.*)/);
                pffGoogleAuth = theAuth[1];
                pffGoogleAuthIsLoggedin = true;
                theObject.doRequest("GET", theObject._url, null, theProcessor, forODS, type);
            } 

            theCall.onError = function (aStatusMsg, Msg) {
				try {
					var errorType = theCall.request.responseText.split('=')[1].replace(/\s*$/,""); 
				
					var errorMessage = '';
				
					switch (errorType) {
						case 'BadAuthentication':
							errorMessage = performancingUI.getLocaleString('errors.blogger.badauthentication');
							break;
						case 'NotVerified':
							errorMessage = performancingUI.getLocaleString('errors.blogger.notverified');
							break;
						case 'TermsNotAgreed':
							errorMessage = performancingUI.getLocaleString('errors.blogger.termsnotagreed');
							break;
						case 'AccountDeleted':
							errorMessage = performancingUI.getLocaleString('errors.blogger.accountdeleted');
							break;
						case 'ServiceDisabled':
							errorMessage = performancingUI.getLocaleString('errors.blogger.servicedisabled');
							break;
						case 'ServiceUnavailable':
							errorMessage = performancingUI.getLocaleString('errors.blogger.serviceunavailable');
							break;
						case 'Unknown':
						default:
							errorMessage = performancingUI.getLocaleString('errors.blogger.unknown', []);
							break;
					}
				
	                alert(errorMessage);
				} catch (e) {
					alert(performancingUI.getLocaleString("upload.error.googleError", [ theCall.request.responseText ]));
				}

				if (typeof scribefireAccountWizard != 'undefined') {
					goTo('login');
				}
            }

            theCall.prepCall();

            theCall.request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            theCall.makeCall();
        }else{
            this.doRequest("GET", this._url, null, processor, forODS, type);
        }
    },

    doRequest: function(method, url, body, processor, forODS, type) {
        var inst = this;
        gPFFLastURIPost = url;
        this._req = new XMLHttpRequest();
        this._req.onreadystatechange = function (aEvt) {
            if(inst._req.readyState == 4) {
                if(inst._req.status == 200 || inst._req.status == 201 || inst._req.status == 204)
                {
                    try
                    {
                        processor(inst, forODS, type);
                    }
                    catch(e)
                    {
                        var localeString = performancingUI.getLocaleString('atomservererror', []);
                        var localeString2 = performancingUI.getLocaleString('atomerrormessage', [e]);
                        alert(localeString + " #101\n" + localeString2 + "\n" + e + "\nServer Response:" + inst._req.responseText);
                    }
                }
                else {
					alert(performancingUI.getLocaleString("bloggerFailed2", [ inst._req.status, inst._req.responseText ]));
                }
            }
        };

        var rval = this._req.open(method, url, true, this._user, this._pass);
        rval = this._req.setRequestHeader("Authorization", "GoogleLogin auth=" +pffGoogleAuth );
        rval = this._req.setRequestHeader("User-Agent", "Mozilla/5.0 (compatible; ScribeFire; http://www.scribefire.com/)");
        rval = this._req.setRequestHeader("Content-Type", "application/atom+xml");
        rval = this._req.send(body); 
    },

    getRecentPosts: function(numPosts, forODS, type) {
        this.doAuth(this.parseRecentPosts, forODS, type);
    },

    getUsersBlogs: function() {
        this.doAuth(this.parseUsersBlogs);
    },

    parseUsersBlogs: function( inst) {
        try {
            var rval = new Array();
            var dom = inst._req.responseXML;

			if (!dom) {
				alert(performancingUI.getLocaleString("bloggerIncompleteResponse"));
				return;
			}

            //gPFFDebugTemp.push(dom);
            //gPFFDebugTemp.push(inst._req.responseText);
            var url = "";
            var id = "";
            var title = "";
            //URL
            var theLinks = dom.getElementsByTagName("link")
            for(i in theLinks){
                try{
                    if(theLinks[i].getAttribute("rel") == "alternate"){
                             url = (theLinks[i].getAttribute("href") ); 
                             break;
                    }
                }catch(e){}
            }
            
            //Title
            var theTitles = dom.getElementsByTagName("title");

			if (theTitles.length == 0) {
				title = "Unknown title";
			}
			else {
				title = theTitles[0].firstChild.nodeValue;
			}
            
            //ID
            var theIDs = dom.getElementsByTagName("id");
            try{
                id = theIDs[0].firstChild.nodeValue.match(/(?:[\S]*feeds\/)([\d]*)(?=\/posts)/)[1];
            }catch(e){
                id = "";
            }
            var obj  =
                {
                    blogName: title,
                    blogid:  id,
                    url:  url
                };
                rval[rval.length++] = obj;
            //listener.onResult(rval);
            performancing_xmlcall.processData(rval, null, 'accountwizard', "", true);
        }
        catch(e) {
			alert(performancingUI.getLocaleString("bloggerProgrammingError", [ e, inst._req.responseText ]));
        }
    },
    
    parseRecentPosts: function(inst, forODS, type) {
        var rval = new Array();

		var theXML = inst._req.responseXML;
		
		/* 
		
		// It was like this when I got here...
        
        var re = /(\<\?xml[0-9A-Za-z\D]*\?\>)/;
        var newstr = inst._req.responseText.replace(re, "");
        
        var re = /<feed[^>]+>/ig;
        newstr = newstr.replace(re, "<feed>");
        
		var re = /<openSearch:[^>]+>.+<\/openSearch:[^>]+>/ig;
        newstr = newstr.replace(re, "");

        var re = /<feedburner:[^>]+>.+<\/feedburner:[^>]+>/ig;
        newstr = newstr.replace(re, "");

		try {
        	var theXML = new XML(newstr);
		} catch (invalidXML) {
			SFLOG(newstr);
			SFLOG(invalidXML);
			throw("The XML returned by the server is invalid.");
		}
		*/
		
		var entries = theXML.getElementsByTagName("entry");
		
		for (var i = 0; i < entries.length; i++) {
            try {
                var catArray = [];

                var theContent = entries[i].getElementsByTagName("content")[0].textContent;
                
                theContent = theContent.replace("<content type=\"xhtml\">\n  ", ""); //Stupid blogger hack
                theContent = theContent.replace("\n</content>", ""); //Stupid blogger hack
                
                var divRegexp = /\<div xmlns\=\'http:\/\/www.w3.org\/1999\/xhtml\'\>|\<div xmlns\=\"http:\/\/www.w3.org\/1999\/xhtml\"\>/;
                var divIndex = theContent.search(divRegexp);
                
                if( divIndex >= 0 && divIndex < 30 ){ //If we have a <div xmlns='http://www.w3.org/1999/xhtml'> at the top
                    theContent = theContent.substring(42, theContent.length - 6); //Get rid of the outer div
                }

                var theTitle = entries[i].getElementsByTagName("title")[0].textContent;
                var theDate = entries[i].getElementsByTagName("published")[0].textContent;
                var val = theDate;

				// Check for a timezone offset
				var possibleOffset = val.substr(-6);
				var hasTimezone = false;
				var minutes = null;

				if (possibleOffset.charAt(0) == "-" || possibleOffset.charAt(0) == "+") {
					var hours = parseInt(possibleOffset.substr(1,2), 10);
					var minutes = (hours * 60) + parseInt(possibleOffset.substr(4,2), 10);

					if (possibleOffset.charAt(0) == "+") {
						minutes *= -1;
					}

					hasTimezone = true;
				}
				
				val = val.replace(/-/gi, "");
				
				var year = parseInt(val.substring(0, 4), 10);
				var month = parseInt(val.substring(4, 6), 10) - 1
				var day = parseInt(val.substring(6, 8), 10);
				var hour = parseInt(val.substring(9, 11), 10);
				var minute = parseInt(val.substring(12, 14), 10);
				var second = parseInt(val.substring(15, 17), 10);
				
				var dateutc =  Date.UTC(year, month, day, hour, minute, second);
				dateutc = new Date(dateutc);
				
				if (!hasTimezone) {
					minutes = new Date(dateutc).getTimezoneOffset();
				}

				var offsetDate = dateutc.getTime();
				offsetDate += (1000 * 60 * minutes);
				dateutc.setTime(offsetDate);
				var date = dateutc;
				
				var thePostURL = entries[i].getElementsByTagName("id")[0].textContent;

				var links = entries[i].getElementsByTagName("link");
				
				for (var j = 0; j < links.length; j++) {
					if (links[j].getAttribute("rel") == 'alternate') {
						var theHREF = links[j].getAttribute("href");
					}
					else if (links[j].getAttribute("rel") == 'edit') {
						var theEditHREF = links[j].getAttribute("href");
					}
				}
				
				var categories = entries[i].getElementsByTagName("category");
				
				for (var j = 0; j < categories.length; j++) {
					catArray.push(categories[j].getAttribute("term"));
				}
				
                var atomid = thePostURL.match( /(?:\/|post-)(\d{5,})(?!\d*\/)/ )[1];
                
                var obj  =
                {
                    description: theContent,
                    title: theTitle,
                    dateCreated: date,
                    postid:  atomid,
                    editURI:  theEditHREF,
                    atomid:  thePostURL,
                    permaLink: theHREF,
                    categories: catArray
                };
				
				SCRIBEFIRE_BLOG.serviceObject.aggregateCategories(catArray);

                rval[rval.length] = obj;
            } catch(e){
				SFLOG(e);
            }
        }
		
		if (!forODS) {
        	performancing_xmlcall.processData(rval, null, 'historycall', "", true);
			gPerformancingUtil.getCategoryList();
		}
		else {
			SF_QUICKBLOG.processRecentPosts(rval, true, type);
		}
    },

    getNamedChild: function(node, name) {
        for(var i=0;i<node.childNodes.length; i++) {
            if(node.childNodes[i].nodeName==name) return node.childNodes[i];
        }
        return null;
    },
    deletePost: function ( postid, aEditURI) {
        var url = this._url;
        if(postid) url += "/" + postid;
        if(aEditURI) url = aEditURI;
        this.doRequest("DELETE", url, null, this.handleDelete);
    },
	
    doPost: function ( method, postid, title, description, date_created, doPublish, aEditURI, aAtomID, isEdit, forODS) {
        var url = this._url;
        if(postid) url += "/" + postid;

        var date = "";
        try{
            date = bfXMLRPC.iso8601Format(date_created);
        }catch(e){
        }

        var body = "";
        body += '<?xml version="1.0" encoding="UTF-8" ?>';
        body += '<entry xmlns="http://www.w3.org/2005/Atom" xmlns:app="http://purl.org/atom/app#">';

        var draft = false;
        if(doPublish == false || doPublish == 'bool0') draft = true;
		
		title = title.replace(/&amp;/g, '&');
		title = gPerformancingUtil.namedEntitiesToNumericEntities(title);
		title = title.replace(/&([^#])/g, "&amp;$1");
		
            //Set the Labels (categories)
			var getLabelArray = "";
            try { getLabelArray = gPerformancingUtil.getArrOfCatChecked('blog-sidebar-listing-categories', false); } catch (e) { }
			
            if( getLabelArray != "" && getLabelArray.length > 0 ){
                for(var i=0; i < getLabelArray.length; i++){
                    body += '<category scheme="http://www.blogger.com/atom/ns#" term="'+getLabelArray[i].replace(/&/g,'&amp;')+'"/>';
                }
            }
            
            body += '<title mode="escaped" type="text">' + title + '</title>';
            body += '<issued>' + date + '</issued>';

			if (date) {
				var validDate = date.substring(0,4) + "-" + date.substring(4,6) + "-" + date.substring(6,8) + "T" + date.substring(9,17) + ".000Z";
				body += '<published>' + validDate + '</published>';
			}

            body += '<content type="xhtml">'

			// Blogger doesn't like named entities.
			description = gPerformancingUtil.namedEntitiesToNumericEntities(description);

            var containsDIV = description.indexOf("<div xmlns=\"http://www.w3.org/1999/xhtml\">");
			
            if(containsDIV >= 0){
                body += description.replace(/&([^#])/g, "&amp;$1");
            }else{
                body += '<div xmlns="http://www.w3.org/1999/xhtml">' + description.replace(/&([^#])/g, "&amp;$1") + '</div>';
            }
            body += '</content>';
			
            if(draft){
                body += '<app:control>';
                body += '  <app:draft>yes</app:draft>';
                body += '</app:control>';
            }

            body += ' </entry>';
		
		if (forODS) {
        	this.doRequest(method, url, body, SF_QUICKBLOG.processPostEdit, doPublish);
		}
		else {
        	this.doRequest(method,url,body,this.parsePosts, doPublish);
		}
    },
    editPost: function ( postid, title, description, date_created, isDraft, aEditURI, aAtomID, forODS) {
		this.doBlockingAuth();
        this.doPost( "PUT", postid, title, description, date_created, isDraft, aEditURI, aAtomID, "isEdit", forODS);
    },
    newPost: function ( title, description, date_created, isDraft) {
        this.doPost( "POST", null, title, description, date_created, isDraft);
    },
    parsePosts: function( inst) {
		var dom = inst._req.responseXML;
		
		if(!dom) {
			// LiveJournal - everone wants to be different, don't they?
			if(inst._req.responseText.match(/OK/)) {
				performancing_xmlcall.processData(1, null, null, "", true);
				return;
			}
			else {
				alert(inst._req.responseText);
				return;
			}
		}
		
		var entries = dom.getElementsByTagName("entry");
		
		if (!entries || entries.length == 0) {
			alert("The server did not return the expected data:\n\n" + inst._req.responseText);
			return;
		}
		
		var rval = new Object();
		
		var entry_n = entries[0];
		var link_n = null;
		var perm_link_n = null;
		
		var atomid_n = inst.getNamedChild(entry_n, "id");
		var atomid = "";
		if (atomid_n) atomid = atomid_n.firstChild.nodeValue;
		
		for (var j = 0; j < entry_n.childNodes.length; j++) {
			if (entry_n.childNodes[j].nodeName == "link") {
				var tmp = entry_n.childNodes[j];
				if(tmp.getAttribute("rel").match(/edit/)) {
					link_n = tmp;
				}
				else if(tmp.getAttribute("rel").match(/self/)) {
					perm_link_n = tmp;
				}
			}
		}
		
		var href = link_n.getAttribute("href");
		rval.editURI = href;
		rval.atomid = atomid;
		href.match(/.+\/(.+)/);
		rval.uid = RegExp.$1;
		
		// Livejournal hackage
		if(rval.editURI.length>0 && rval.atomid.length==0) {
			var perm_link = perm_link_n.getAttribute("href");
			if(perm_link.match(/livejournal/)) {
				perm_link.match(/.+livejournal.com\/users\/(.+?)\/(.+?)\./);
				rval.atomid = "urn:lj:livejournal.com:atom1:" + RegExp.$1 + ":" + RegExp.$2;
			}
		}
		
		performancing_xmlcall.processData(rval, null, 'newpostcall', "", true );
    },
    
    handleDelete: function( inst) {
        //listener.onResult(1);
        performancing_xmlcall.processData(1, null, 'deletehistorycall', "", true);
    }
}

function createPostRequest(args) {
	/**
	 * Generates a POST request body for uploading.
	 *
	 * args is an associative array of the form fields.
	 *
	 * Example:
	 * var args = { "field1": "abc", "field2" : "def", "fileField" : { "file": theFile, "headers" : [ "X-Fake-Header: foo" ] } };
	 * 
	 * theFile is an nsILocalFile; the headers param for the file field is optional.
	 *
	 * This function returns an array like this:
	 * { "requestBody" : uploadStream, "boundary" : BOUNDARY }
	 * 
	 * To upload:
	 *
	 * var postRequest = createPostRequest(args);
	 * var req = new XMLHttpRequest();
	 * req.open("POST", ...);
	 * req.setRequestHeader("Content-Type","multipart/form-data; boundary="+postRequest.boundary);
	 * req.setRequestHeader("Content-Length", (postRequest.requestBody.available()));
	 * req.send(postRequest.requestBody);
	 */
	
	function stringToStream(str) {
		function encodeToUtf8(oStr) {
			var utfStr = oStr;
			var uConv = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
			uConv.charset = "UTF-8";
			utfStr = uConv.ConvertFromUnicode(oStr);

			return utfStr;
		}
		
		str = encodeToUtf8(str);
		
		var stream = Components.classes["@mozilla.org/io/string-input-stream;1"].createInstance(Components.interfaces.nsIStringInputStream);
		stream.setData(str, str.length);
		
		return stream;
	}
	
	function fileToStream(file) {
		var fpLocal  = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
		fpLocal.initWithFile(file);

		var finStream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream);                
		finStream.init(fpLocal, 1, 0, false);

		var bufStream = Components.classes["@mozilla.org/network/buffered-input-stream;1"].createInstance(Components.interfaces.nsIBufferedInputStream);
		bufStream.init(finStream, 9000000);
		
		return bufStream;
	}
	
	var mimeSvc = Components.classes["@mozilla.org/mime;1"].getService(Components.interfaces.nsIMIMEService);
	const BOUNDARY = "---------------------------32191240128944"; 
	
	var streams = [];
	
	for (var i in args) {
		var buffer = "--" + BOUNDARY + "\r\n";
		buffer += "Content-Disposition: form-data; name=\"" + i + "\"";
		streams.push(stringToStream(buffer));
		
		if (typeof args[i] == "object") {
			buffer = "; filename=\"" + args[i].file.leafName + "\"";
			
			if ("headers" in args[i]) {
				if (args[i].headers.length > 0) {
					for (var q = 0; q < args[i].headers.length; q++){
						buffer += "\r\n" + args[i].headers[q];
					}
				}
			}
			
			var theMimeType = mimeSvc.getTypeFromFile(args[i].file);
			
			buffer += "\r\nContent-Type: " + theMimeType;
			buffer += "\r\n\r\n";
			
			streams.push(stringToStream(buffer));
			
			streams.push(fileToStream(args[i].file));
		}
		else {
			buffer = "\r\n\r\n";
			buffer += args[i];
			buffer += "\r\n";
			streams.push(stringToStream(buffer));
		}
	}
	
	var buffer = "--" + BOUNDARY + "--\r\n";
	streams.push(stringToStream(buffer));
	
	var uploadStream = Components.classes["@mozilla.org/io/multiplex-input-stream;1"].createInstance(Components.interfaces.nsIMultiplexInputStream);
	
	for (var i = 0; i < streams.length; i++) {
		uploadStream.appendStream(streams[i]);
	}
	
	return { "requestBody" : uploadStream, "boundary": BOUNDARY };
}